package debtbundler.mathematics;


import static org.junit.Assert.*;

import org.junit.*;

import debtbundler.mathematics.GaussianLinSysSolver;

public class GaussianEliminationTest {
	
	@BeforeClass 
	public static void enableLogging() {
		debtbundler.logging.ConfigurationReader.setDefaultConf();
	}

	@Before
	public void setUp() throws Exception {
	}

	@After
	public void tearDown() throws Exception {
	}
	
	/**
	 * Tests solving of an m x m system with a unique solution  
	 */
	@Test
	public void testSolve1() {
		
		double[][] coefMatrix = {	{1, -1, -2}, 
									{-3, 5, 8}, 
									{2, -1, -5}
								};
		double[] rhsVector = {-1, 7, 4};
		
		GaussianLinSysSolver solver = new GaussianLinSysSolver(coefMatrix, rhsVector);
		
		assertEquals("Test rank of matrix", 3, solver.getRank());
		assertEquals("Test the number of solutions", 1, solver.getNumberOfSolutions());
		
		double[] expectedResult = {-1.0, 4.0, -2.0};
		double[] result = solver.getSolutionVector();
		for (int i=0; i<expectedResult.length; ++i) {
			assertEquals("Test x["+i+"]", expectedResult[i], result[i], 0);
		}		
		
	}
	
	/**
	 * Tests solving of an m x m system with infinitely many solutions (i.e. a parameterized solution).  
	 */
	@Test
	public void testSolve2() {
		
		double[][] coefMatrix = {	{1, -1, -2, 1}, 
									{-3, 5, 8, 3}, 
									{2, -1, -5, 5},
									{0, 1, 1, 3}
								};
		double[] rhsVector = {-1, 7, 4, 2};
		
		GaussianLinSysSolver solver = new GaussianLinSysSolver(coefMatrix, rhsVector);
		
		assertEquals("Test rank of matrix", 3, solver.getRank());
		assertEquals("Test the number of solutions", Integer.MAX_VALUE, solver.getNumberOfSolutions());
		
		double[] expectedResult = {-1.0, 4.0, -2.0, 0.0};
		double[] result = solver.getSolutionVector();
		for (int i=0; i<expectedResult.length; ++i) {
			assertEquals("Test x["+i+"]", expectedResult[i], result[i], 0);
		}
			
	}
	
	/**
	 * Tests solving of an m x n system with m > n and infinitely many solutions (i.e. a parameterized solution).
	 */
	@Test
	public void testSolve3() {
		
		double[][] coefMatrix = {	{1, -1, -2, 1}, 
									{-3, 5, 8, 3}, 
									{2, -1, -5, 5},
									{0, 1, 1, 3},
									{-1, 4, 5, 8}
								};
		double[] rhsVector = {-1, 7, 4, 2, 7};
		
		GaussianLinSysSolver solver = new GaussianLinSysSolver(coefMatrix, rhsVector);
		
		assertEquals("Test the rank of the system", 3, solver.getRank());
		assertEquals("Test the number of solutions", Integer.MAX_VALUE, solver.getNumberOfSolutions());
		
		double[] expectedResult = {-1.0, 4.0, -2.0, 0.0};
		double[] result = solver.getSolutionVector();
		for (int i=0; i<expectedResult.length; ++i) {
			assertEquals("Test x["+i+"]", expectedResult[i], result[i], 0);
		}
		
	}
	
	/**
	 * Tests solving of an m x m system with zero solutions.  
	 */
	@Test
	public void testSolve4() {		

		double[][] coefMatrix = {	
									{1, -1, -2}, 
									{-3, 5, 8}, 
									{2, -1, -5},
									{2, -1, -5}
								};
		double[] rhsVector = {-1, 7, 4, 8};
		
		GaussianLinSysSolver solver = new GaussianLinSysSolver(coefMatrix, rhsVector);
		
		assertEquals("Test rank of matrix", 3, solver.getRank());
		assertEquals("Test the number of solutions", 0, solver.getNumberOfSolutions());
	}
	
	/**
	 * Tests solving of an m x n system with m < n and infinitely many solutions (i.e. a parameterized solution).
	 */
	@Test
	public void testSolve5() {
		
		double[][] coefMatrix = {	{1, -1, -2, 1}, 
									{-3, 5, 8, 3}
								};
		double[] rhsVector = {-1, 7};
		
		GaussianLinSysSolver solver = new GaussianLinSysSolver(coefMatrix, rhsVector);
		
		
		assertEquals("Test rank of matrix", 2, solver.getRank());
		assertEquals("Test the number of solutions", Integer.MAX_VALUE, solver.getNumberOfSolutions());
		
		double[] expectedResult = {1.0, 2.0};
		double[] result = solver.getSolutionVector();
		for (int i=0; i<expectedResult.length; ++i) {
			assertEquals("Test x["+i+"]", expectedResult[i], result[i], 0);
		}
		
		
	}
	
	@Test
	public void testSolve6() {		
		double[][] coefMatrix = {	{-1, 0, 0, 0}, 
									{0, -1, 0, 0},
									{0, 0, -1, 0},
									{0, 0, 0, -1},
									{1, 1, 1, 1}
								};
		double[] rhsVector = {-30, -30, -30, -30, 120};
		
		GaussianLinSysSolver solver = new GaussianLinSysSolver(coefMatrix, rhsVector);
		
		
		assertEquals("Test rank of matrix", 4, solver.getRank());
		assertEquals("Test the number of solutions", 1, solver.getNumberOfSolutions());
		
		double[] expectedResult = {30.0, 30.0, 30.0, 30.0};
		double[] result = solver.getSolutionVector();
		for (int i=0; i<expectedResult.length; ++i) {
			assertEquals("Test x["+i+"]", expectedResult[i], result[i], 0);
		}
		
		
	}
	
	@Test
	public void testSolve7() {		
		double[][] coefMatrix = {	{-1, -1, -1, 0}, 
									{0, 0, 0, -1},
									{1, 0, 0, 0},
									{0, 1, 0, 0},
									{0, 0, 1, 1}
								};
		double[] rhsVector = {-66, -46, 4, 14, 94};
		
		GaussianLinSysSolver solver = new GaussianLinSysSolver(coefMatrix, rhsVector);
		
		
		assertEquals("Test rank of matrix", 4, solver.getRank());
		assertEquals("Test the number of solutions", 1, solver.getNumberOfSolutions());
		
		double[] expectedResult = {4, 14, 48, 46};
		double[] result = solver.getSolutionVector();
		for (int i=0; i<expectedResult.length; ++i) {
			assertEquals("Test x["+i+"]", expectedResult[i], result[i], 0);
		}
		
		
	}


}
